#include <algorithm>
#include <set>
#include <vector>
#include <map>
#include <stdio.h>
std::vector<int> xx = {1,2,3};

static void make_component_grade_combination(std::vector<std::vector<int>>& result, std::vector<int>& grade_vector, int add, int total, int index) {
    static const std::vector<int>& grades = xx;

    if (total - add <= 0){
        result.push_back(grade_vector);
        return;
    }

    if (grades.size() <= index + 1) {
        grade_vector.resize(add);
        grade_vector.resize(total, grades[index]);
        result.push_back(grade_vector);
        return;
    }

    std::vector<int> xx;
    for (int i = 0; i <= total - add; ++i)
        xx.emplace_back(i);

    for (const auto& num : xx) { 
        grade_vector.resize(add);
        grade_vector.resize(add + num, grades[index]);
        make_component_grade_combination(result, grade_vector, add + num, total, index + 1);
    } 
}

/*static void make_component_grade_combination(std::vector<std::vector<int>>& result, std::vector<int>& grade_vector, int index) {*/
    //const std::set<int>& grades = {1, 2, 3};

    //const int vector_size = int(grade_vector.size());

    //if (index >= vector_size) {
        //result.push_back(grade_vector);
        //return;
    //}


    //for (const auto& grade : grades) {
        //if (index - 1 >= 0 && grade_vector[index - 1] > grade) continue;
        //grade_vector[index] = grade;
        //make_component_grade_combination(result, grade_vector, index + 1);
    //}
//}

static void get_component_grade_combination(int player_count, int dest_total_grade, std::vector<int>** result) {

    static std::map<int, std::vector<std::vector<int>>> count2combinations;
    auto it = count2combinations.find(player_count);
    do {
        if (it != count2combinations.end()) break;

        //std::vector<int> grade_vector(player_count, 0);
        //make_component_grade_combination(count2combinations[player_count], grade_vector, 0);
        std::vector<int> grade_vector;
        make_component_grade_combination(count2combinations[player_count], grade_vector, 0, player_count, 0);

        printf("-------2--------------------\n");
        it = count2combinations.find(player_count);
        if (it == count2combinations.end()) return;

        printf("-------3--------------------\n");

        for (const auto& xx : it->second) { 
            printf("---------------------------\n");
            for (const auto& x : xx) { 
                printf("%d ", x);
                
            } 
            printf("\n");
        } 

        std::sort(it->second.begin(), it->second.end(), [] (const std::vector<int>& other, const std::vector<int>& another) {
            return std::accumulate(other.begin(), other.end(), 0) >
                   std::accumulate(another.begin(), another.end(), 0);
        });
    } while (0);

    printf("xxxx:%ld\n", it->second.size());

    auto sit = std::find_if(it->second.begin(), it->second.end(), [dest_total_grade] (const std::vector<int>& other) {
        return std::accumulate(other.begin(), other.end(), -dest_total_grade) <= 0;
    });
    printf("xx:%d\n", sit == it->second.end());
    for (const auto& a : *sit) { 
        printf("%d-\n", a);
    } 

    if (sit != it->second.end()) *result = &(*sit);
}


int main(int argc, char **argv) {
    std::vector<int> * xx = nullptr;
    get_component_grade_combination(4, 7, &xx);

    if (xx != nullptr) {
        for (const auto& x : *xx) { 
            printf("%d\n", x);
        } 
    }
    printf("xxxxxx\n");
    return 0;
}

/*int main(int argc, char **argv) {*/
    //std::vector<std::vector<int>> xx = {{1,2,3,4}, {1,3,4}};
    //std::sort(xx.begin(), xx.end(), [] (const std::vector<int>& a, const std::vector<int>& b) {
        //return std::accumulate(a.begin(), a.end(), -5) <
               //std::accumulate(b.begin(), b.end(), -5);
    //});

    //for (const auto& x : xx) {
        //printf("---------------\n");
        //for (const auto& xa : x) {
            //printf("%d\n", -xa);
        //}
    //}
    //return 0;
/*}*/
